package chartCraft.tableDesk;

import java.awt.Desktop;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Observable;
import java.util.Observer;

import javax.swing.ButtonGroup;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JRadioButtonMenuItem;

import chartCraft.ChartCraftController;
import chartCraft.Log;
import chartCraft.SaveStateManager;
import chartCraft.command.CommandBroker;
import chartCraft.graphDesk.DraggableChart;
import chartCraft.graphDesk.DraggableItem;
import chartCraft.model.LocationModel;
import chartCraft.model.TopModel;
import chartCraft.model.Model.NotifyingMessage;

public class ChartCraftTopMenuBar extends JMenuBar implements Observer{

	private static final long serialVersionUID = 1L;

	public static final String ADD = "Add...";
	public static final String CHANGE = "Change...";
	public static final String HIDE = "Hide";
	public static final String SHOW = "Show";

	private ChartCraftController mChartCraftController;
	private TopModel mTopModel;
	private SaveStateManager mSaveState;
	private CommandBroker mCommandBroker;

	private JRadioButtonMenuItem mPieChartItem;
	private JRadioButtonMenuItem mVerticalBarItem;
	private JRadioButtonMenuItem mHorizontalBarItem;
	private JRadioButtonMenuItem mVerticalStackedBarChartItem;
	private JRadioButtonMenuItem mHorizontalStackedBarChartItem;

	private JMenuItem mChangeBackgroundItem;
	private JMenuItem mRemoveBackgroundItem;
	private JMenuItem mHideBackgroundItem;
	private JMenuItem deleteRowItem;
	private JMenuItem deleteColumnItem;
	private JMenuItem newItem;
	private JMenuItem saveItem;
	private JMenuItem saveAsItem;
	private JMenuItem undoItem; 
	private JMenuItem redoItem; 

	public ChartCraftTopMenuBar(ChartCraftController chartCraftController,
			TopModel topModel, SaveStateManager saveState, CommandBroker commandBroker) {
		mChartCraftController = chartCraftController;

		setModel(topModel);
		
		mSaveState = saveState;
		mSaveState.addObserver(this);
		
		mCommandBroker = commandBroker;
		mCommandBroker.addObserver(this);

		createMenu();
		refleshAllMenu();
	}

	private void createMenu() {
		createFileMenu();
		createEditMenu();
		createChartMenu();
		createTableMenu();
		createBackgroundMenu();
		createAboutMenu();
		createHelpMenu();
	}

	private void createHelpMenu() {
		JMenu helpMenu = new JMenu("Help");

		JMenuItem onlineHelpItem = new JMenuItem("Online Help");
		helpMenu.add(onlineHelpItem);
		onlineHelpItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				String link = "http://www.wix.com/christinampoon/chartcrafthelp";
				try {
					URI url = new URI(link);
					Desktop.getDesktop().browse(url);  
				} catch (Exception e) {
					JOptionPane.showMessageDialog(null,
						    "Fail to open the help page. " + e.getLocalizedMessage(),
						    "Error",
						    JOptionPane.ERROR_MESSAGE);
				}
			}});

		add(helpMenu);	

	}

	private void createAboutMenu() {
		JMenu aboutMenu = new JMenu("About");

		JMenuItem aboutItem = new JMenuItem("About ChartCraft");
		aboutMenu.add(aboutItem);
		aboutItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				String link = "http://www.wix.com/christinampoon/chartcraftabout";
				try {
					URI url = new URI(link);
					Desktop.getDesktop().browse(url);  
				} catch (Exception e) {
					JOptionPane.showMessageDialog(null,
						    "Fail to open the about page. " + e.getLocalizedMessage(),
						    "Error",
						    JOptionPane.ERROR_MESSAGE);
				}
			}});

		add(aboutMenu);			
	}

	private void createBackgroundMenu() {
		JMenu backgroundMenu = new JMenu("Background");

		mChangeBackgroundItem = new JMenuItem("Change...");
		backgroundMenu.add(mChangeBackgroundItem);
		mChangeBackgroundItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				mChartCraftController.changeBackgroundImage();				
			}
		});

		mRemoveBackgroundItem = new JMenuItem("Remove");
		backgroundMenu.add(mRemoveBackgroundItem);
		mRemoveBackgroundItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				mChartCraftController.deleteBackgroundImage();				
			}
		});

		mHideBackgroundItem = new JMenuItem("Hide");
		backgroundMenu.add(mHideBackgroundItem);
		mHideBackgroundItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if (mHideBackgroundItem.getText().equals(HIDE)) {
					mChartCraftController.setImageHidding(true);
				} else if (mHideBackgroundItem.getText().equals(SHOW)) {
					mChartCraftController.setImageHidding(false);
				} else {
					Log.e(this, "Unhandled state");
				}
			}
		});
		refreshBackgroundMenu();
		add(backgroundMenu);		
	}

	private void createTableMenu() {
		JMenu tableMenu = new JMenu("Table");

		JMenuItem insertRowItem = new JMenuItem("Add Row");
		tableMenu.add(insertRowItem);
		insertRowItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				mChartCraftController.insertNewLocation();				
			}
		});

		deleteRowItem = new JMenuItem("Delete Last Row");
		tableMenu.add(deleteRowItem);
		deleteRowItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				mChartCraftController.deleteLastLocation();				
			}
		});

		JMenuItem insertColumnItem = new JMenuItem("Add Column");
		tableMenu.add(insertColumnItem);
		insertColumnItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				mChartCraftController.insertNewSeries();				
			}
		});

		deleteColumnItem = new JMenuItem("Delete Last Column");
		tableMenu.add(deleteColumnItem);
		deleteColumnItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				mChartCraftController.deleteLastSeries();				
			}
		});

		add(tableMenu);	

	}

	private void createChartMenu() {
		JMenu chartMenu = new JMenu("Chart");

		JMenuItem undoItem = new JMenuItem("Add Chart");
		chartMenu.add(undoItem);
		undoItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				mChartCraftController.insertNewLocation();				
			}
		});

		//chart type here
		chartMenu.addSeparator();
		ButtonGroup group = new ButtonGroup();

		mPieChartItem = new JRadioButtonMenuItem("Pie Chart");
		group.add(mPieChartItem);
		chartMenu.add(mPieChartItem);
		mPieChartItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				mChartCraftController.changeChartTypeTo(LocationModel.PIE_CHART);
			}
		});

		mVerticalBarItem = new JRadioButtonMenuItem("Bar Chart - Vertical");
		group.add(mVerticalBarItem);
		chartMenu.add(mVerticalBarItem);
		mVerticalBarItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				mChartCraftController.changeChartTypeTo(LocationModel.VERTICAL_BAR_CHART);
			}
		});

		mHorizontalBarItem = new JRadioButtonMenuItem("Bar Chart - Horizontal ");
		group.add(mHorizontalBarItem);
		chartMenu.add(mHorizontalBarItem);
		mHorizontalBarItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				mChartCraftController.changeChartTypeTo(LocationModel.HORIZONTAL_BAR_CHART);
			}
		});

		mVerticalStackedBarChartItem = new JRadioButtonMenuItem("Stacked Bar Chart - Vertical");
		group.add(mVerticalStackedBarChartItem);
		chartMenu.add(mVerticalStackedBarChartItem);
		mVerticalStackedBarChartItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				mChartCraftController.changeChartTypeTo(LocationModel.VERTICAL_STACKED_BAR_CHART);
			}
		});

		mHorizontalStackedBarChartItem = new JRadioButtonMenuItem("Stacked Bar Chart - Horizontal");
		group.add(mHorizontalStackedBarChartItem);
		chartMenu.add(mHorizontalStackedBarChartItem);	
		mHorizontalStackedBarChartItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				mChartCraftController.changeChartTypeTo(LocationModel.HORIZONTAL_STACKED_BAR_CHART);
			}
		});

		add(chartMenu);		
	}

	private void createEditMenu() {
		JMenu editMenu = new JMenu("Edit");

		undoItem = new JMenuItem("Undo");
		editMenu.add(undoItem);
		undoItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				mChartCraftController.undo();				
			}
		});

		redoItem = new JMenuItem("Redo");
		editMenu.add(redoItem);	
		redoItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				mChartCraftController.redo();				
			}
		});

		add(editMenu);
	}

	private void createFileMenu() {
		JMenu fileMenu = new JMenu("File");

		newItem = new JMenuItem("New Document");
		fileMenu.add(newItem);
		newItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				mChartCraftController.newDocument();
			}
		});
		

		JMenuItem openItem = new JMenuItem("Open...");
		fileMenu.add(openItem);
		openItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				mChartCraftController.open();				
			}
		});

		saveItem = new JMenuItem("Save");
		fileMenu.add(saveItem);
		saveItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				mChartCraftController.save();				
			}
		});

		saveAsItem = new JMenuItem("Save As...");
		fileMenu.add(saveAsItem);
		saveAsItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				mChartCraftController.saveAs();				
			}
		});

		JMenuItem quitItem = new JMenuItem("Quit");
		fileMenu.add(quitItem);
		quitItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				mChartCraftController.quit();				
			}
		});
		

		add(fileMenu);
	}

	public void setModel(TopModel model) {
		mTopModel = model;
		mTopModel.addObserver(this);
		
		reloadFromState();
	}

	private void refleshChartMenu() {
		int chartType = mTopModel.getChartType();
		switch(chartType) {
		case LocationModel.HORIZONTAL_BAR_CHART:
			mHorizontalBarItem.setSelected(true);
			break;
		case LocationModel.HORIZONTAL_STACKED_BAR_CHART:
			mHorizontalStackedBarChartItem.setSelected(true);
			break;
		case LocationModel.VERTICAL_BAR_CHART:
			mVerticalBarItem.setSelected(true);
			break;
		case LocationModel.VERTICAL_STACKED_BAR_CHART:
			mVerticalStackedBarChartItem.setSelected(true);
			break;
		case LocationModel.PIE_CHART:
			mPieChartItem.setSelected(true);
			break;
		}
	}

	private void refreshBackgroundMenu() {

		if (mTopModel.isImagieHiding()) {
			mHideBackgroundItem.setText(SHOW);
		} else {
			mHideBackgroundItem.setText(HIDE);
		}

		if (mTopModel.getBackgroundImage() == null) {
			mChangeBackgroundItem.setText(ADD);
			mRemoveBackgroundItem.setEnabled(false);
			mHideBackgroundItem.setEnabled(false);
			mHideBackgroundItem.setText(SHOW);
		} else {
			mChangeBackgroundItem.setText(CHANGE);
			mRemoveBackgroundItem.setEnabled(true);
			mHideBackgroundItem.setEnabled(true);
		}
	}

	private void refreshTableMenu() {
		if (mTopModel.getNoOfLocations() <= 1) {
			deleteRowItem.setEnabled(false);
		} else {
			deleteRowItem.setEnabled(true);
		}

		if (mTopModel.getNoOfSeries() <= 1) {
			deleteColumnItem.setEnabled(false);
		} else {
			deleteColumnItem.setEnabled(true);
		}
	}

	@Override
	public void update(Observable arg0, Object arg1) {


		if (arg0 == mTopModel) {
			NotifyingMessage msg = (NotifyingMessage) arg1;
			String action = msg.getAction();

			if (action == TopModel.CHART_TYPE_CHANGED) {
				refleshChartMenu();
			} else if (action == TopModel.BACKGROUND_DATA_UPDATED) {
				refreshBackgroundMenu();
			} else if (action == TopModel.BACKGROUND_HIDDING_CHANGED) {
				refreshBackgroundMenu();
				
			} else if (action == TopModel.INSERT_NEW_LOCATION_MODEL) {
				LocationModel locationModel = (LocationModel) msg.getObject();
				locationModel.addObserver(this);
				refreshTableMenu();

			} else if (action == TopModel.DELETE_LOCATION_MODEL) {
				LocationModel locationModel = (LocationModel) msg.getObject();
				locationModel.deleteObserver(this);
				refreshTableMenu();
			}

		} else if (arg0 instanceof LocationModel) {
			NotifyingMessage msg = (NotifyingMessage) arg1;
			String action = msg.getAction();
			
			if (action == LocationModel.STUCTURE_CHANGE) {
				refreshTableMenu();
			}
		} else if (arg0 == mSaveState) {
			refleshAllMenu();
			
		} else if (arg0 == mCommandBroker) {
			refleshAllMenu();
		}
	}
	
	private void reloadFromState() {
		for (LocationModel locaitonModel: mTopModel.getAllLocationModels()) {
			locaitonModel.addObserver(this);
		}
	}

	private void refleshAllMenu() {
		refleshChartMenu();
		refreshBackgroundMenu();
		refreshTableMenu();
		refreshUndoRedoMenu();
		refreshFileMenu();
		
	}

	private void refreshUndoRedoMenu() {
		redoItem.setEnabled(mCommandBroker.canRedo());
		undoItem.setEnabled(mCommandBroker.canUndo());
	}
	
	private void refreshFileMenu() {		
		//do nothing
	}

}
